import { NetDispatcher } from "../tools/NetDispatcher";
import GameConfig from "../GameConfig";

export class Server extends Laya.EventDispatcher {
    private _socket: Laya.Socket;
    private serviceProto;
    private _connectReady: boolean;
    private addr = ""
    private _logger: Console;
    public options: WsServerOptions;
    constructor(serviceProto, options: WsServerOptions) {
        super();
        // TestLogin.Install.login();
        this.init(serviceProto, options);
    }


    private init(serviceProto, options: WsServerOptions) {
        this._connectReady = false;
        this._socket = new Laya.Socket();
        this._socket.endian = Laya.Byte.LITTLE_ENDIAN;
        this._socket.on(Laya.Event.OPEN, this, this.onSocketOpen);
        this._socket.on(Laya.Event.CLOSE, this, this.onSocketClose);
        this._socket.on(Laya.Event.MESSAGE, this, this.onMessageReveived);
        this._socket.on(Laya.Event.ERROR, this, this.onConnectError);
        this.options = options;
        this._logger = this.options.logger;
        //加载协议映射表
        this.serviceProto = serviceProto;;
    }

    public connect() {
        // let addr = "ws://47.105.184.36:3000";//http://47.105.184.36:3000/web/index.html
        this._socket.connectByUrl(this.addr);
    }

    public revonnect() {
        this._socket.close();
        // this._socket.connectByUrl(this.addr);
    }

    public logout() {
        this._socket.close();
    }

    /**
     * 表示连接成功，可以通信了
     */
    public onSocketOpen() {
        console.log("connect open");
        this._connectReady = true;
        this.event(ServerStatus.Opened)
        // this._heartTimer.loop(10000, this, this.onHeartBeat);
    }

    /**
     * 表示连接已经关闭，或者打开连接失败
     */
    public onSocketClose() {
        console.log("connect close");
        this.revonnect();
        this.event(ServerStatus.Closed)
        this._connectReady = false;
    }

    public sendHeartData(nameId:number) {
        if (this.options.jsonEnabled) {
            let heart = {
                id: nameId,
                data: {}
            }
            this._socket.send(JSON.stringify(heart));
            this._socket.flush();
        } else {
            let ba: Laya.Byte = new Laya.Byte();
            ba.endian = Laya.Byte.LITTLE_ENDIAN;
            ba.writeUint16(nameId);//
            ba.writeUint16(2);
            this._socket.send(ba.buffer);
            this._socket.flush();
        }
    }

    public sendData(nameId: number, data: any, message?: any) {
        if (!this._connectReady) {
            console.log("sendData socket close");
            this.event(ServerStatus.Closed)
            return;
        }

        let msg: any = this.serviceProto[nameId];
        if (!msg) {
            console.log("没有ID" + nameId + "的协议")
            return;
        }
        if (this.options.jsonEnabled) {
            this._sendJsonData(nameId, data);
        } else {
            this._sendBufferData(nameId, message, msg, data);
        }

        //console.log("send data:", name, ",id:", nameId);
    }

    private _sendJsonData(id: number, data: any) {
        let json = { id, data }
        this._socket.send(JSON.stringify(json));
        this._socket.flush();
    }

    private _sendBufferData(nameId: number, message: any, msg: any, data: any) {
        let name: string = `${msg.res.pName}.${msg.res.mName}`;
        // let name:string = msg.res.pName;
        // console.log("name=" + name);
        let buffer = message.encode(data).finish();
        let pkg: Laya.Byte = new Laya.Byte();
        pkg.endian = Laya.Byte.LITTLE_ENDIAN;
        pkg.writeUint16(nameId);
        pkg.writeUint16(buffer.length + 2);
        pkg.writeArrayBuffer(buffer);

        this._socket.send(pkg.buffer);
        this._socket.flush();
    }
    /**
      * 收到的消息
      */
    public onMessageReveived(data: any) {

        if (this.options.jsonEnabled) {
            this._onMessageJson(data);
        } else {
            this._onMessageBuffer(data);
        }
    }

    private _onMessageJson(data: any) {
        if (typeof data === 'string') {
            let datajson = JSON.stringify(data);
            let dataparse = JSON.parse(datajson);
            if (dataparse.id == void 0 || !this.serviceProto[dataparse.id]) {
                // return { isSucc: false, errMsg: `Cannot find service ID: ${dataparse.id}` };
                console.error(`Cannot find service ID: ${dataparse.id}`)
            } else {
                NetDispatcher.dispatch(dataparse.id, dataparse);
            }
        }
        else {
            console.error("data no string")
        }
    }

    private _onMessageBuffer(data: any) {
        let bytes: Laya.Byte = new Laya.Byte();
        bytes.writeArrayBuffer(data);
        bytes.pos = 0;
        bytes.endian = Laya.Socket.LITTLE_ENDIAN;

        let nameId: number = bytes.getUint16();
        let len: number = bytes.getUint16();
        // console.log("nameId"+nameId)
        // console.log("len"+len)
        switch (nameId) {
            case 2:
                console.log("收到心跳");
                break;
            default:
                let msg: any = this.serviceProto[nameId];
                if (!msg) {
                    console.log("没有ID" + nameId + "的协议")
                    // break;
                    return;
                }
                let name: string = `${msg.res.pName}.${msg.res.mName}`;
                // let name:string = msg.res.pName;

                //console.log("name=" + name)
                // let c2s_login2 = protobuf.C2S_Login.decode(arr)
                let buffer = bytes.getUint8Array(4, bytes.length - 4);
                NetDispatcher.dispatch(nameId, buffer);
                break;
        }
    }

    /**
      * 连接错误
      */
    public onConnectError(e: Event) {
        console.log("connect error");
        this.event("CONNECT_ERROR");
        this._connectReady = false;
    }




    // private onHeartBeat() {
    //     if (this._connectReady) {
    //         // let ba: Laya.Byte = new Laya.Byte();
    //         // ba.endian = Laya.Byte.LITTLE_ENDIAN;
    //         // ba.writeUint16(2);
    //         // ba.writeUint16(2);
    //         // ba.writeUint16(2);
    //         let heart = {
    //             id: 2,
    //             data: {
    //                 'name': 'test'
    //             }
    //         }

    //         this._socket.send(JSON.stringify(heart));
    //         this._socket.flush();
    //     } else {
    //         console.log("In heartBeat, the connection id closed!")
    //     }
    // }
}

export class WsServerOptions {
    addr: string;
    logger: Console;
    jsonEnabled: boolean;
}

export enum ServerStatus {
    Opening = "OPENING",
    Opened = "OPENED",
    Closing = "CLOSING",
    Closed = "CLOSED"
}